package com.lkathous.dev.tools.handler;

import com.github.difflib.DiffUtils;
import com.github.difflib.patch.Patch;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author liaokai
 * @since 2024/4/6 15:45
 */
public class ProjectCompareHandler {

    /** 是否自动同步文件 */
    private static final boolean SYNC_FILE = true;
    /** 来源项目地址（tms-logistics */
    private static final String SOURCE_PROJECT = "D:\\workspace\\dev\\tms\\tms-logistics2";
    /** 目标项目地址（tms-yc */
    private static final String TARGET_PROJECT = "D:\\workspace\\dev\\tms\\tms-yc";

//    private static final String[] IGNORE_LIST = new String[]{};
    private static final String[] IGNORE_LIST = new String[]{
            "\\constant\\RocketMqTagConstants.java",
            "\\constant\\RocketMqConsumerGroupConstants.java",
            "\\constant\\YcConstants.java",
    };

    private static final Pattern PARAM_PATTERN = Pattern.compile("-s(.*?) -t(.*)");

    /**
     * 
     * @author liaokai
     * @since 2024/4/6 15:47
     * @param input
     */
    public void handle(String input) throws IOException {
//        Matcher matcher = PARAM_PATTERN.matcher(input);
//        String sourcePath = null;
//        String targetPath = null;
//        if (matcher.find()) {
//            sourcePath = matcher.group(1).trim();
//            targetPath = matcher.group(2).trim();
//        }

        // 对比java文件
        String sourcePath = SOURCE_PROJECT + "\\tms-charteredcarmanager-provider\\src\\main\\java\\com\\kyexpress\\erp\\tms\\charteredcarmanager\\provider";
        String targetPath = TARGET_PROJECT + "\\tms-yc-provider\\src\\main\\java\\com\\kyexpress\\erp\\tms\\yc\\provider";
        compareDir(sourcePath, targetPath, sourceStr -> StringUtils.replaceAll(sourceStr, "\\.charteredcarmanager\\.", ".yc."), SYNC_FILE);
        // 对比java文件
        String sourcePath3 = SOURCE_PROJECT + "\\tms-charteredcarmanager-api\\src\\main\\java\\com\\kyexpress\\erp\\tms\\charteredcarmanager\\api";
        String targetPath3 = TARGET_PROJECT + "\\tms-yc-api\\src\\main\\java\\com\\kyexpress\\erp\\tms\\yc\\api";
        compareDir(sourcePath3, targetPath3, sourceStr -> StringUtils.replaceAll(sourceStr, "\\.charteredcarmanager\\.", ".yc."), SYNC_FILE);
        // 对比java文件
        String sourcePath4 = SOURCE_PROJECT + "\\tms-charteredcarmanager-client\\src\\main\\java\\com\\kyexpress\\erp\\tms\\charteredcarmanager\\client";
        String targetPath4 = TARGET_PROJECT + "\\tms-yc-client\\src\\main\\java\\com\\kyexpress\\erp\\tms\\yc\\client";
        compareDir(sourcePath4, targetPath4, sourceStr -> StringUtils.replaceAll(sourceStr, "\\.charteredcarmanager\\.", ".yc.")
                .replaceAll("\\-logistics\"", "-yc\""), SYNC_FILE);

        // 对比mapper文件
        String sourcePath2 = SOURCE_PROJECT + "\\tms-charteredcarmanager-provider\\src\\main\\resources\\com\\kyexpress\\erp\\tms\\charteredcarmanager\\provider\\mapper";
        String targetPath2 = TARGET_PROJECT + "\\tms-yc-provider\\src\\main\\resources\\com\\kyexpress\\erp\\tms\\yc\\provider\\mapper";
        compareDir(sourcePath2, targetPath2, sourceStr -> StringUtils.replaceAll(sourceStr, "\\.charteredcarmanager\\.", ".yc."), SYNC_FILE);
    }

    private void compareDir(String sourcePath, String targetPath, Function<String, String> sourceFileFormat, boolean isSyncFile) throws IOException {
        Collection<File> sourceFiles = FileUtils.listFiles(new File(sourcePath), new String[]{"java","xml"}, true);
        Collection<File> targetFiles = FileUtils.listFiles(new File(targetPath), new String[]{"java","xml"}, true);

        System.out.println("source: " + sourcePath);
        System.out.println("source文件数" + sourceFiles.size());
        System.out.println("target: " + targetPath);
        System.out.println("target文件数" + targetFiles.size());
        System.out.println();

        Map<String, File> sourceMap = sourceFiles.stream().collect(Collectors.toMap(
                file -> StringUtils.remove(file.getAbsolutePath(), sourcePath), Function.identity(), (a, b) -> a));
        Map<String, File> targetMap = targetFiles.stream().collect(Collectors.toMap(
                file -> StringUtils.remove(file.getAbsolutePath(), targetPath), Function.identity(), (a, b) -> a));

        Set<String> sourceFilenames = sourceMap.keySet();
        Set<String> targetFilenames = targetMap.keySet();

        List<String> lessList = new ArrayList<>();
        List<String> sameList = new ArrayList<>();
        for (String sourceFilename : sourceFilenames) {
            if (!targetFilenames.contains(sourceFilename)) {
                lessList.add(String.format("%s 【缺少】", sourceFilename));

                if (isSyncFile) {
                    File sourceFile = sourceMap.get(sourceFilename);
                    String sourceStr = FileUtils.readFileToString(sourceFile, StandardCharsets.UTF_8);
                    sourceStr = sourceFileFormat.apply(sourceStr);

                    String newFilename = targetPath + StringUtils.remove(sourceFile.getAbsolutePath(), sourcePath);
//                    System.out.println(newFilename);
                    FileUtils.write(new File(newFilename), sourceStr, StandardCharsets.UTF_8, false);
                }
            } else {
                sameList.add(sourceFilename);
            }
        }
        List<String> moreList = new ArrayList<>();
        for (String targetFilename : targetFilenames) {
            if (!sourceFilenames.contains(targetFilename)) {
                moreList.add(String.format("%s 【多出】", targetFilename));

                if (isSyncFile) {
                    FileUtils.deleteQuietly(targetMap.get(targetFilename));
                }
            }
        }

        System.out.println(String.format("1.数量差异，source对比target，多出%d，缺少%d", moreList.size(), lessList.size()));
        lessList.sort(String::compareTo);
        lessList.forEach(System.out::println);
        moreList.sort(String::compareTo);
        moreList.forEach(System.out::println);
        System.out.println();

        try {
            checkSameFile(sourceMap, targetMap, sameList, sourceFileFormat, isSyncFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void checkSameFile(Map<String, File> sourceMap, Map<String, File> targetMap, List<String> sameList, Function<String, String> sourceFileFormat, boolean syncFile) throws IOException {
        List<String> resp = new ArrayList<>();

        for (String filename : sameList) {
            if (ArrayUtils.contains(IGNORE_LIST, filename)) {
                continue;
            }

            File source = sourceMap.get(filename);
            File target = targetMap.get(filename);

            String sourceStr = FileUtils.readFileToString(source, StandardCharsets.UTF_8);
            String targetStr = FileUtils.readFileToString(target, StandardCharsets.UTF_8);

            sourceStr = sourceFileFormat.apply(sourceStr);
            if (!sourceStr.equals(targetStr)) {
                resp.add(filename + " 【差异】");
                Patch<String> patches = DiffUtils.diff(Arrays.asList(StringUtils.split(sourceStr))
                        , Arrays.asList(StringUtils.split(targetStr)));
                resp.add(patches.toString());

                if (syncFile) {
                    FileUtils.write(target, sourceStr, StandardCharsets.UTF_8, false);
                }
            }
        }

        System.out.println(String.format("2.文件差异，数量%d", resp.size() / 2));
        System.out.println();
        resp.forEach(System.out::println);
        System.out.println();
    }
}
